export function typeOf(data) {
    const toString = Object.prototype.toString,
        map = {
            "[object Boolean]": "boolean",
            "[object Number]": "number",
            "[object String]": "string",
            "[object Function]": "function",
            "[object Array]": "array",
            "[object Date]": "date",
            "[object RegExp]": "regExp",
            "[object Undefined]": "undefined",
            "[object Null]": "null",
            "[object Object]": "object",
            "[object File]": "file",
            "[object Argument]": "array"
        };
    const type = toString.call(data);
    return map[type] || type.replace(/\[+|\]+|s+/gi, "").toLowerCase();
}

export class QueryString {
    static stringify(data, { sep = '&', eq = '=', callback, encode, maxKeys = 0, simple = true } = {}) {
        if (typeOf(encode) !== 'function') {
            encode = function (val) {
                return encodeURIComponent(val);
            }
        }
        const arr = (QueryString.serialize(...arguments) || []).map(function (item) {
            return item[0] + eq + encode(item[1]);
        })
        return arr.join(sep);
    }
    static serialize(data, { callback, maxKeys = 0, simple = true } = {}) {
        if (typeOf(data) !== 'object') return [];
        if (typeOf(callback) !== 'function') {
            callback = function (key, prefix, type) {
                if (simple && type === 'array') return prefix;
                if (!prefix) return key;
                return `${prefix}[${key}]`;
            }
        }
        const arr = [],
            iterator = function (obj, prefix, callback, deep = 0) {
                const type = typeOf(obj); ++deep;
                if (maxKeys > 0 && deep > maxKeys) return;
                if (type === 'object' || type === 'array') {
                    Object.keys(obj).forEach(function (key) {
                        const prefixkey = callback.call(this, key, prefix, type);
                        if (prefixkey === undefined || prefixkey === false) return;
                        iterator(this[key], prefixkey, callback, deep);
                    }, obj);
                } else {
                    if (obj === undefined || obj === null) obj = '';
                    if (typeof obj === 'string') obj = obj.trim();
                    arr.push([prefix, obj]);
                }
            }
        iterator(data, undefined, callback);
        return arr;
    }
    static parse(data = "", { sep = '&', eq = '=' } = {}) {
        if (typeOf(data) !== 'string') return data;
        const source = {};
        data = decodeURIComponent(data).split(sep);
        data.forEach(function (str) {
            let [keys = '', val] = str.split(eq), obj = source;
            keys = keys.replace(/\](\[)?/g, '.').split(/[\[\]\.]/g).filter(function (key) {
                return !!key;
            });
            const length = keys.length - 1;
            keys.forEach(function (key, index) {
                if (length <= index) {
                    const value = obj[key];
                    if (value === undefined) {
                        obj[key] = val;
                    } else if (typeOf(value) === 'array') {
                        value.push(val);
                    } else {
                        obj[key] = [value, val];
                    }
                } else {
                    if (!obj[key]) {
                        obj[key] = {}
                    } else {
                        obj = obj[key];
                    }
                }
            })
        })
        return source;
    }
}


export function transferEmpty(val, newVal = '', emptyList) {
    return (emptyList || [null, undefined]).indexOf(val) > -1 ? newVal : val
}

// 单位换算
export function conversionUnit(val, form = 'cm', to = 'inch', decimal = 4) {
    const RATE = {
        'inch-cm': 2.54,
        'cm-inch': 1/2.54,
        'lb-g': 453.592,
        'g-lb': 1/453.592,
        'lb-oz':16,
        'oz-lb':1/16,
        'kg-lbs': 2.2046226,
        'lbs-kg': 0.4535924
    }
    const rate = RATE[`${form}-${to}`];
    if (!val || val == 0 || !rate) return val;
    return (val * rate).toFixed(decimal);
}

export function userBrowser(context) {
    context = context || this;
    try {
        const userAgent = navigator.userAgent.toLowerCase(),
            bool = ['edge', 'firefox', 'chrome', 'opera', 'webkit', 'blink'].some(item => {
                return userAgent.indexOf(item) > -1
            });
        if (!bool) {
            throw new Error('暂不支持该版本浏览器');
        }
    } catch (err) {
        const browsers = [
            {
                name: 'Chrome 浏览器',
                href: 'https:\/\/www.google.cn/chrome/'
            }, {
                name: 'Firefox 浏览器',
                href: 'http:\/\/www.firefox.com.cn/download/'
            }, {
                name: 'Edge 浏览器',
                href: 'https:\/\/www.microsoft.com/zh-cn/windows/microsoft-edge/'
            }, {
                name: '360 浏览器',
                href: 'https:\/\/browser.360.cn/se/'
            }, {
                name: '360 极速浏览器',
                href: 'https:\/\/browser.360.cn/ee/'
            }, {
                name: 'QQ 浏览器',
                href: 'https:\/\/browser.qq.com'
            }, {
                name: 'QQ 浏览器',
                href: 'https:\/\/browser.qq.com'
            }, {
                name: 'Safari 浏览器',
                href: 'https:\/\/support.apple.com/zh_CN/downloads/safari'
            },
        ]
        context.$VNotice.error({
            title: '暂不支持该浏览器;请下载以下版本。',
            render(h) {
                return h('div', {
                    style: "overflow:hidden;"
                }, browsers.map((item) => {
                    return h('a', {
                        style: "float:left;padding:9px 6px;",
                        attrs: {
                            href: item.href
                        }
                    }, item.name)
                }))
            },
            duration: 60
        });
        return false;
    }
    return true;
}


// 用于扩展Storage
export function extendStorage(interceptors) {
    const resetStorageProto = function (_interceptors) {
        const { set: setHander, get: getHandler } = _interceptors || interceptors || {};
        const handlers = {
            getOrigin: function (key, options) {
                if (options && typeof options !== 'object') {
                    options = { prefix: options };
                } else {
                    options = options || {};
                }
                key = options.prefix != undefined ? `${options.prefix}@${key}` : key;
                let value = this._getItem(key);
                if (typeof value === 'string' && value[0] === '{' && value[value.length - 1] === '}') {
                    try {
                        let val = JSON.parse(value);
                        if (!val._storage_) return value;
                        value = val;
                        if (typeof this.getHandler === 'function' && !this.getHandler(key, value, options)) {
                            this._removeItem(key);
                            return
                        }
                        if (value.persistent) return value;
                        if (value.expire && Date.now() > new Date(value.expire).getTime()) {
                            this._removeItem(key);
                            return;
                        }
                    } catch (error) {
                        // eslint-disable-next-line no-console
                        console.error(error)
                    }
                }
                return value;
            },
            getConfig: function (key, options) {
                if (arguments.length == 0) throw new Error("1 argument required");
                const value = this.getOrigin(key, options)
                if (value != undefined && typeof value === 'object') {
                    delete value.data;
                    return value;
                }
                return {};
            },
            getItem: function (key, options) {
                if (arguments.length == 0) throw new Error("1 argument required");
                const value = this.getOrigin(key, options)
                if (value != undefined && typeof value === 'object') return value.data;
                return value;
            },
            setItem: function (key, value, options) {
                if (arguments.length < 2) throw new Error(`2 argument required`);
                if (options && typeof options !== 'object') {
                    options = { prefix: options };
                } else {
                    options = options || {};
                }
                const val = {
                    _storage_: true,
                    data: value,
                }
                if (options.persistent) val.persistent = true;
                try {
                    if (typeof this.setHander === 'function') {
                        this.setHander(key, val, options);
                    }
                    if (options.maxAge) {
                        val.expire = Date.now() + options.maxAge * 1000;
                    }
                    if (options.expire) {
                        val.expire = new Date(options.expire).getTime();
                    }
                } catch (error) {
                    // eslint-disable-next-line no-console
                    console.error(error)
                }
                return this._setItem(options.prefix != undefined ? `${options.prefix}@${key}` : key, JSON.stringify(val));
            },
            //设置永久数据缓存快捷方式
            setPersistentItem:function (key, value, options) {
                if (options && typeof options !== 'object') {
                    options = { prefix: options };
                } else {
                    options = options || {};
                }
                options={scope: '', version: '',...options,persistent:true};
                return this.setItem(key, value, options);
            },
            removeItem: function (key, options) {
                if (arguments.length == 0) throw new Error("1 argument required");
                const value = this.getOrigin(key, options);
                if (options && typeof options !== 'object') {
                    options = { prefix: options };
                } else {
                    options = options || {};
                }
                if (value != undefined && typeof value === 'object' && value.persistent && !options.persistent) return;
                this._removeItem(options.prefix != undefined ? `${options.prefix}@${key}` : key);
            },
            clear: function (options) {
                if (typeof options !== 'object') {
                    options = { persistent: !!options };
                } else {
                    options = options || {};
                }
                if (options.persistent && options.prefix == undefined) {
                    return this._clear();
                }
                const keys = Object.keys(this);
                keys.forEach(key => {
                    this.removeItem(key, options)
                })
            },
            //拦截器
            setHander,
            getHandler,
            //兼容
            get: function (key, options = { prefix: '' }) {
                return this.getItem(key, options)
            },
            set: function (key, value, options = { prefix: '' }) {
                return this.setItem(key, value, options)
            },
            remove: function (key, options = { prefix: '' }) {
                return this.removeItem(key, options)
            },
            removeAll: function (prefix = '', persistent = false) {
                return this.clear({ prefix, persistent })
            },
        }
        const fnKey = ["getItem", "setItem", "removeItem", "clear"];
        fnKey.forEach(key => {
            Storage.prototype[`_${key}`] = Storage.prototype[key];
        });
        Object.assign(Storage.prototype, handlers)
        // console.log(Object.keys(Storage.prototype))
    }
    const resetStorage = function (storage, initOpts = { scope: '', version: '' }) {
        const storageData = storage === 'localStorage' ? localStorage : sessionStorage;
        initOpts = { ...initOpts };
        Object.defineProperty(global, storage, {
            get: function () {
                return new Proxy(storageData, {
                    get: function (target, propKey, receiver) {
                        let value = Reflect.get(target, propKey, receiver);
                        if (Storage.prototype.hasOwnProperty(propKey)) {
                            return typeof value === 'function' ? value.bind(target) : value;
                        }
                        return target.getItem(propKey, initOpts);
                    },
                    set: function (target, propKey, value, receiver) {
                        target.setItem(propKey, value, initOpts)
                        return true
                    }
                });
            },
            configurable: true,
            enumerable: true,
        })
    }
    resetStorageProto({
        get: function (key, value, options) {
            const handler = function (val) {
                if (val === '' || val === '*' || val === '/') return '';
                return global.SYSID
            }
            return !((value.version && value.version !== process.env.VUE_APP_VERSION) || (value.scope && value.scope !== handler(options.scope)))
        },
        set: function (key, value, options) {
            const handler = function (val, isVersion) {
                if (val === '' || val === '*' || val === '/') return '';
                return isVersion ? (process.env.VUE_APP_VERSION || '') : global.SYSID
            }
            value.scope = handler(options.scope);
            value.version = handler(options.version, true);
            if (!value.scope) delete value.scope;
            if (!value.version) delete value.version;
        }
    });
    resetStorage('localStorage');
    resetStorage('sessionStorage');
}


/**
 * 跨页面销毁SessionStorage Store
 */
export function syncSessionStorage(key = 'TEMP_CHEAR_SESSION') {
    const handleStorage = function (e) {
        e = e || global.event;
        // eslint-disable-next-line no-console
        console.log(e);
        if (e.key === null || (e.key === key && e.newValue)) {
            // eslint-disable-next-line no-console
            console.log('跨页面执行清除sessionStorage');
            sessionStorage.clear(true);
            localStorage.removeAll('', true);
        }
    }
    if (global.addEventListener) {
        global.addEventListener("storage", handleStorage, false);
    } else {
        global.attachEvent("onstorage", handleStorage);
    }
}


export function initEnvPrefix(prefix) {
    Object.defineProperty(global, 'envPrefix', {
        configurable: false,
        value: prefix ? `${prefix}-` : '',
        writable: false,
        enumerable: false,
    })
}

/**
 * 更新版本号
 */
export function updateVersion(cb) {
    try {
        let preVersion = `${localStorage.getItem("VERSION") || ''}`;
        let curVersion = `${process.env.VUE_APP_VERSION || ''}`;
        localStorage.setItem("VERSION", curVersion, { scope: '', persistent: true, version: '' });
        if (preVersion !== curVersion && /^\d+\.\d+\.\d+@\d+$/.test(curVersion) && /^\d+\.\d+\.\d+@\d+$/.test(preVersion)) {
            curVersion = curVersion.split('.');
            preVersion = preVersion.split('.');
            if ((curVersion[0] != preVersion[0] || curVersion[1] != preVersion[1]) && typeof cb === 'function') {
                //主版本更新 major | minor
                cb(true);
            }
        }
    } catch (error) {
        // eslint-disable-next-line no-console
        console.error(error);
    }
}


/**
 * 处理多域名问题
 * @param {*} url
 * @param {*} defaultName
 */
export function handleHostname(url = '', defaultName = '.thebizark.com') {
    let regMatch = null;
    if (url && (regMatch = /\.\w+\.[a-z]{2,6}$/i.exec(location.hostname) || [defaultName])) {
        regMatch = regMatch[0];
        // eslint-disable-next-line no-useless-escape
        return url.replace(/^(https?:\/\/)?([\da-z\.-]+)?\.\w+\.[a-z]{2,6}/i, function (match, p1, p2) {
            return `${p1 || ''}${p2 || ''}${regMatch}`;
        });
    }
    return url;
}

//处理copy
export function handleCopy(target) {
    if (window.clipboardData) {//ie
        window.clipboardData.clearData();
        window.clipboardData.setData("Text", target);
        return true;
    }
    if (document.body.createTextRange) {
        let range = document.body.createTextRange();
        range.moveToElementText(target);
        range.select();
        document.execCommand("Copy");
        return true;
    }
    if (window.getSelection) {
        let selection = window.getSelection();
        let range = document.createRange();
        range.selectNodeContents(target);
        selection.removeAllRanges();
        selection.addRange(range);
        document.execCommand("Copy");
        return true;
    }
    return false;
}
